package com.abai.doubi.utils;

import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class AliSTTUtil {
    public static final String APP_KEY = "NNJR7bYumMWc0RnB";
    @Resource
    private NlsClient nlsClient = new NlsClient("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
    public String processAndGetResult(MultipartFile audioFile, int sampleRate) {
        try {
            return processAndGetResult(audioFile.getInputStream(), sampleRate);
        } catch (IOException e) {
            log.error("语音识别出错", e);
        }
        return "语音识别出错";
    }

    /**
     * 处理语音文件并返回识别结果
     *
     * @param filepath  音频文件路径
     * @param sampleRate 音频采样率(8000或16000)
     * @return 识别的文本结果
     */
    public String processAndGetResult(String filepath, int sampleRate) {
        try {
            return processAndGetResult(new FileInputStream(filepath), sampleRate);
        } catch (IOException e) {
            log.error("Error processing speech recognition", e);
        }
        return "语音识别出错";
    }

    /**
     * 处理语音文件并返回识别结果
     *
     * @param inputStream  音频文件路径
     * @param sampleRate 音频采样率(8000或16000)
     * @return 识别的文本结果
     */
    public String processAndGetResult(InputStream inputStream, int sampleRate) {
        StringBuilder recognizedText = new StringBuilder();
        CompletableFuture<String> resultFuture = new CompletableFuture<>();
        log.info("开始语音识别");
        SpeechRecognizer recognizer = null;
        try {
            SpeechRecognizerListener listener = new SpeechRecognizerListener() {
                @Override
                public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
                    log.info("Intermediate result: {}", response.getRecognizedText());
                }

                @Override
                public void onRecognitionCompleted(SpeechRecognizerResponse response) {
                    String result = response.getRecognizedText();
                    log.info("Final recognition result: {}", result);
                    recognizedText.append(result);
                    resultFuture.complete(result);
                }

                @Override
                public void onStarted(SpeechRecognizerResponse response) {
                    log.info("Speech recognition started, task_id: {}", response.getTaskId());
                }

                @Override
                public void onFail(SpeechRecognizerResponse response) {
                    String errorMsg = "Recognition failed, task_id: " + response.getTaskId() +
                            ", status: " + response.getStatus() +
                            ", status_text: " + response.getStatusText();
                    log.error(errorMsg);
                    resultFuture.completeExceptionally(new RuntimeException(errorMsg));
                }
            };

            recognizer = new SpeechRecognizer(nlsClient, listener);
            recognizer.setAppKey(APP_KEY);
            recognizer.setFormat(InputFormatEnum.PCM);

            if (sampleRate == 16000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
            } else if (sampleRate == 8000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
            }

            recognizer.setEnableIntermediateResult(true);
            recognizer.addCustomedParam("enable_voice_detection", true);

            long now = System.currentTimeMillis();
            recognizer.start();
            log.info("ASR start latency: {} ms", (System.currentTimeMillis() - now));

            byte[] buffer = new byte[3200];
            int len;

            while ((len = inputStream.read(buffer)) > 0) {
                log.debug("Sending data pack length: {}", len);
                recognizer.send(buffer, len);
                int deltaSleep = getSleepDelta(len, sampleRate);
                Thread.sleep(deltaSleep);
            }

            log.info("ASR waiting for completion");
            recognizer.stop();
            inputStream.close();

            // 等待识别完成并返回结果
            return resultFuture.get();
        } catch (Exception e) {
            log.error("Error processing speech recognition", e);
            throw new RuntimeException("Speech recognition failed", e);
        } finally {
            if (recognizer != null) {
                recognizer.close();
            }
        }
    }

    /**
     * 根据二进制数据大小计算对应的同等语音长度
     *
     * @param dataSize   数据大小
     * @param sampleRate 采样率(仅支持8000或16000)
     * @return 计算得到的睡眠时长
     */
    public static int getSleepDelta(int dataSize, int sampleRate) {
        // 仅支持16位采样
        int sampleBytes = 16;
        // 仅支持单通道
        int soundChannel = 1;
        return (dataSize * 10 * 8000) / (160 * sampleRate);
    }
}